#include "esp8266.h"
#include <QDebug>

ESP8266::ESP8266(QObject *parent) : QSerialPort(parent)
{
    setPortName("/dev/ttySAC1"); // 设置为你的串口号
    setBaudRate(QSerialPort::Baud115200); // 设置波特率
    setDataBits(QSerialPort::Data8); // 设置数据位
    setParity(QSerialPort::NoParity); // 设置无校验
    setStopBits(QSerialPort::OneStop); // 设置停止位

    if (open(QIODevice::ReadWrite))
    { // 打开串口
        //qDebug() << "Port3 opened successfully!";

        connect(this, &QSerialPort::readyRead, this, &ESP8266::handleReadyRead);
        //connect(this, &QSerialPort::errorOccurred, this, &Serial::handleError);

        sendATCommand();
    }
    else
    {
        //qDebug() << "Failed to open port:" << errorString();
        return ;
    }

    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [&]()
    {
        static int count = 0;
        count++;
        if(count >= 20 * 10)
        {
            count = 0;
            //subscribe();
        }

        if(list.size() <= 0)
            return ;
        QByteArray data = list.first();

        quint8 len = data.length();
        currentCommand = SendDataLengthCmd; // 更新当前命令

        // 发送数据长度指令
        QByteArray lengthCommand = QString("AT+CIPSEND=%1\r\n").arg(len).toUtf8();
        write(lengthCommand); // 发送数据长度指令
    });
    timer->start(1000);
}

void ESP8266::sendDataToServer(const char *topic, const QByteArray &data)
{
    if(tcpConnect)
    {
        foreach(QByteArray node, list)
        {
            if(node.contains(topic))
            {
                qDebug() << "remove";
                list.removeOne(node);
            }
        }
        list.append(data);
    }

}

void ESP8266::handleReadyRead()
{
    QByteArray data = readAll();
    response.append(data);
    //if(response.contain("\r\n"))
    {
        //qDebug() << "recv:" << response;
        // 查找 \r\n 的位置
        int index = response.indexOf("\r\n");
        while (index != -1)
        {
            // 截取 \r\n 前面的数据
            //qDebug()  << "******" << response;
            QByteArray line = response.left(index);
            if (line.contains("OK"))
            {
                //qDebug() << "Command executed successfully";
                if (currentCommand == ATCommand) {
                    sendSTACmd();
                } else if (currentCommand == STACmd) {
                    sendConnectAPCmd();
                } else if(currentCommand == ConnectAPCmd){
                    sendCheckConnectionCmd();
                }
                else if(currentCommand == CheckConnectionCmd){
                    sendCheckConnectionCmd();
                    currentCommand = CheckTcpCmd;
                }
                else if (currentCommand == SendDataLengthCmd)
                {
                    if(list.size() > 0)
                    {
                        //qDebug() << "send:" << list.first();
                        // 发送实际数据
                        write(list.first()); // 发送数据包
                        write("\r\n"); // 结束数据发送
                        list.pop_front();
                    }

                }
            }
            else if (currentCommand == ChecAPCmd)
            {
                if(line.contains("2"))
                {
                    QTimer::singleShot(5000, this, [&]
                    {
                        establishTCPConnection();
                    }
                    );

                }
            }
            else if(currentCommand == CheckTcpCmd){
                if(line.contains("3")){
                    tcpConnect = true;
                    subscribe();
                }
            }
            else if(line.contains("WIFI CONNECTED"))
            {
                QTimer::singleShot(5000, this, [&]
                {
                    establishTCPConnection();
                }
                );
            }
            else
            {

                //qDebug() << "error Response:" << line;
                if(line.contains("true") || line.contains("false"))
                    emit sigData(line);
                else
                {
                    //qDebug() << "Failed to execute command:" << currentCommand;
                }
            }
            // 删除截取掉的数据
            response = response.mid(index + 2);
            // 继续查找下一个 \r\n 的位置
            index = response.indexOf("\r\n");
        }
    }

}

void ESP8266::subscribe()
{
    //qDebug() <<"subs cribe";
    char topics[MAX_MSG_SIZE];
    int len = 0;

    // 将所有主题合并到一个字符串中，用逗号分隔
    len += snprintf(topics + len, sizeof(topics) - len, "%s", TOPIC_LED);
    len += snprintf(topics + len, sizeof(topics) - len, ",%s", TOPIC_FAN);
    len += snprintf(topics + len, sizeof(topics) - len, ",%s", TOPIC_H);
    len += snprintf(topics + len, sizeof(topics) - len, ",%s", TOPIC_S);
    len += snprintf(topics + len, sizeof(topics) - len, ",%s", TOPIC_W);
    len += snprintf(topics + len, sizeof(topics) - len, ",%s", TOPIC_SUN);

    // 发送合并后的主题
    char msgbuf[MAX_MSG_SIZE];
    sprintf(msgbuf, "cmd=1&uid=%s&topic=%s\r\n", UID, topics);
    sendDataToServer("sub", msgbuf);
}

void ESP8266::handleError(QSerialPort::SerialPortError error) {
    //qDebug() << "Serial port error:" << error;
}

void ESP8266::sendATCommand()
{
    write("AT\r\n");
    currentCommand = ATCommand;
}

void ESP8266::sendSTACmd()
{
    write("AT+CWMODE=1\r\n");
    currentCommand = STACmd;
}

void ESP8266::sendConnectAPCmd() {
    write("AT+CWJAP=\"gui\",\"12345678\"\r\n");
    currentCommand = ConnectAPCmd;
}

void ESP8266::sendGetIPCmd()
{
    //qDebug() << "sendGetIPCmd";
    write("AT+CIFSR\r\n");
    //currentCommand = GetIPCmd;
}

void ESP8266::establishTCPConnection()
{
    //119.91.109.180", 8344
    //qDebug() << "establish TCPConnection";// 192.168.203.169  119.91.109.180
    write("AT+CIPSTART=\"TCP\",\"119.91.109.180\",8344\r\n");
    currentCommand = CheckConnectionCmd; // 更新当前命令
}

void ESP8266::handleConnected()
{
    //qDebug() << "Successfully connected to server";
}


void ESP8266::sendCheckConnectionCmd()
{
    write("AT+CIPSTATUS\r\n"); // 发送查询网络连接信息的指令
    currentCommand = ChecAPCmd; // 更新当前命令
}
